home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 013 / edisk.arc / EDISK.ASM next >
Encoding:
Assembly Source File  |  1985-11-10  |  24.6 KB  |  538 lines

  1.  
  2. TITLE EDISK - INSTALLABLE DEVICE DRIVER FOR A HIGH MEMORY VIRTUAL DISK
  3. ;11/10/85
  4. ;       This ram disk uses the 128K portion of memory above 640K be-
  5. ;       ginning at segment D000:0000 and ending at F000:0000.
  6. ;       The original code comes from the DOS 2.0 Technical Manual, later
  7. ;       modified by Rex McAnally to allow variable sizes. (I have
  8. ;       included his original notes below.)
  9. ;       The code has been modified in accordence with the POWER USER
  10. ;       column in PC Magazine, Oct. 15, 1985.  It includes the following
  11. ;       features:
  12. ;                a. It will assemble with both versions 1 & 2 MACRO
  13. ;                   Assenbler
  14. ;
  15. ;                b. The program initializes the 128K RAM to prevent the
  16. ;                   dreaded PARITY error (DOS won't do it)
  17. ;
  18. ;                c. The contents of the Ram disk will survive a warm boot
  19. ;                   (Ctl-Alt-Del)
  20. ;
  21. ;       You have to provide the 128K ram memory addressable at segment D000
  22. ;       Note: This 128K was reserved for ROM based programs like those found
  23. ;             for the PC jr.  None are available for the PC/PC-XT so the
  24. ;             memory space is normally unusable & wasted.  It can't be added
  25. ;             to DOS as it is'nt continuous with the 640K user's area.
  26. ;
  27. ;       The easiest way to add this memory to your PC is to buy an IBM
  28. ;       64/256K Memory Expansion Option board, install 128K on it, and
  29. ;       set its DIP switches for a start address of D000 like so:
  30. ;
  31. ;                 switch     1   2   3   4   5   6   7   8
  32. ;                 position  off off  on off off  on off off
  33. ;
  34. ;       Not all memory or combo memory boards will do.  Most don't allow
  35. ;       you to choose the absolute starting segment address.
  36. ;
  37. ;       To use this program:
  38. ;
  39. ;                1.  Assemble this program using the MACRO Assembler
  40. ;
  41. ;                2.  Link the resultant .OBJ file using LINK (DOS utility)
  42. ;
  43. ;                3.  Convert the resultant .EXE file to binary form using
  44. ;                    EXE2BIN (also a DOS utility), and name it EDISK.SYS
  45. ;
  46. ;                4.  Copy the EDISK.SYS file to your BOOT/Root directory
  47. ;
  48. ;                5.  Add DEVICE=EDISK.SYS as the **FIRST** line of your
  49. ;                    CONFIG.SYS file.  It   M-u-s-t  be first as the program
  50. ;                    has to know whether it sees a first or a subsequent
  51. ;                    Boot.  Some Devive drivers cause a double Boot and
  52. ;                    if they precede EDISK.SYS they will cause EDISK to
  53. ;                    think an initial cold Boot is a warm Boot.  This
  54. ;                    screws up the Ram Disk data preserve function and
  55. ;                    will most likely cause your system to hang up.
  56. ;
  57. ;       A driver that adds 64K above the 640K user area to DOS (IF you have
  58. ;       Ram there), such as MEMM.SYS works OK as long as it follows the EDISK
  59. ;       driver in CONFIG.SYS.
  60. ;
  61. ;       I have marked the lines I modified with  EM  and those I added
  62. ;       with  EM-A.  By now this code has been pretty well hacked and
  63. ;       could stand some cleaning up, but it works fine as is.  Feel free
  64. ;       to clean it up or improve it further.
  65. ;
  66. ;                         ENJOY,
  67. ;                                  Bill Wacker
  68. ;
  69. ;
  70. ;Rex McNally's unmodified notes follow:
  71. ;
  72. ;       This was originally the virtual disk device contained in
  73. ;       the DOS 2.0 manual (listing only).
  74. ;
  75. ;       The code has been modified to allow a ram disk of more than
  76. ;       180k.  This can be specified in 2 ways.
  77. ;       (1). Changing the RAMDISK equate statment to the desired size in
  78. ;              1 K increments, reassembling, linking, using EXE2BIN,
  79. ;              to convert to "com" file format. (see DOS 2.0 manual on
  80. ;              device drivers.
  81. ;       (2). Rename the "VDISK.COM" file to "VDISK.XXX",
  82. ;            Using DEBUG you can modify the size by changing offsets
  83. ;            29-30 hex in the file. offset 29 = low order byte, 30 = h/o
  84. ;            These 2 bytes contain the size in 1K increments.
  85. ;
  86. ;       The current maximum limit is 512K (0200 hex).
  87. ;
  88. ;       All modified lines of code have been labeled with <RM> comments.
  89. ;       Please feel free to play with this, I am considering enhancing it
  90. ;       to ask the operator for a size before completing the device
  91. ;       installation.
  92. ;       Rex McAnally
  93. ;
  94.               PAGE
  95. CSEG          SEGMENT PARA PUBLIC 'CODE'
  96. ;
  97. ;***              MACRO DEFINITIONS
  98. ;
  99. STATUS        MACRO    STATE,ERR,RC
  100.               IFIDN    <STATE>,<DONE>
  101.                 OR     ES:WORD PTR SRH_STA_FLD[BX],0100H
  102.               ENDIF
  103.               IFIDN    <STATE>,<BUSY>
  104.                 OR     ES:WORD PTR SRH_STA_FLD[BX],0200H
  105.               ENDIF
  106.               IFIDN    <ERR>,<ERROR>
  107.                 OR     ES:WORD PTR SRH_STA_FLD[BX],1000H
  108.               ENDIF
  109.               IFNB     <RC>
  110.                 OR     ES:WORD PTR SRH_STA_FLD[BX],RC
  111.               ENDIF
  112.               ENDM
  113. ;
  114. ;***Equates
  115. ;
  116. ;***Size
  117. ;
  118. SECT          EQU      512         ; size of a sector                  <RM>
  119. RAMDISK       EQU      128         ; size of ramdisk in 1k increments <RM> <EM>
  120. FATSIZE       EQU      1           ; # sect in 1 copy of fat           <RM>
  121. ;
  122. ;***Read/Write
  123. ;
  124. SRH           EQU      0           ;Static request header start
  125. SRH_LEN       EQU      13          ;  "       "      "    length
  126. SRH_LEN_FLD   EQU      SRH         ;  "       "      "    length field
  127. SRH_UCD_FLD   EQU      SRH+1       ;  "       "      "    unit code field
  128. SRH_CCD_FLD   EQU      SRH+2       ;  "       "      "    command code fld
  129. SRH_STA_FLD   EQU      SRH+3       ;  "       "      "    status field
  130. SRH_RES_FLD   EQU      SRH+5       ;  "       "      "    reserved area fld
  131. MD            EQU      SRH+SRH_LEN ;Media descriptor byte
  132. MD_LEN        EQU      1           ;  "       "        "  length
  133. DTA           EQU      MD+MD_LEN   ;Disk transfer address
  134. DTA_LEN       EQU      4           ;DTA length
  135. COUNT         EQU      DTA+DTA_LEN ;Byte/Sector count
  136. COUNT_LEN     EQU      2           ;      "       "   length
  137. SSN           EQU      COUNT+COUNT_LEN ;Starting sector number
  138. SSN_LEN       EQU      2               ;   "       "       "   length
  139. ;
  140. ;***Media check
  141. ;
  142. RET_BYTE      EQU      MD+MD_LEN   ;Byte returned from driver
  143. ;
  144. ;***Build BPB
  145. ;
  146. BPBA_PTR      EQU      DTA+DTA_LEN
  147. BPBA_PTA_LEN  EQU      4
  148. ;
  149. ;***Init
  150. ;
  151. UNITS         EQU      SRH+SRH_LEN
  152. UNITS_LEN     EQU      1
  153. BR_ADDR_0     EQU      UNITS+UNITS_LEN
  154. BR_ADDR_1     EQU      BR_ADDR_0+2
  155. BR_ADDR_LEN   EQU      4
  156. BPB_PTR_OFF   EQU      BR_ADDR_0+BR_ADDR_LEN
  157. BPB_PTR_SEG   EQU      BPB_PTR_OFF+2
  158. ;
  159. ;
  160. VDSK          PROC     FAR
  161.               ASSUME   CS:CSEG,ES:CSEG,DS:CSEG
  162. BEGIN:
  163. START         EQU      $
  164. ;
  165. ;***Special device header
  166. ;
  167. NEXT_DEV      DD       -1          ;Pointer to next device
  168. ATTRIBUTE     DW       2000H       ;Block device (NON-IBM FORMAT)
  169. STATEGY       DW       DEV_STATEGY ;Pointer to device stategy
  170. INTERRUPT     DW       DEV_INT     ;Pointer to device interrupt handler
  171. DEV_NAME      DB       1           ;Number of block devices
  172.               DB       7 DUP(?)    ;7 bytes of filler
  173. RH_OFF        DW       ?           ;Request header offset
  174. RH_SEG        DW       ?           ;Request header segment
  175. ;
  176. ;***BIOS parameter block
  177. ;
  178. BPB           EQU      $
  179.               DW       SECT                   ;Sector size             <RM>
  180.               DB       1                      ;Sectors/allocation unit
  181.               DW       1                      ;Number of reserved sectors
  182.               DB       2                      ;Number of FATS
  183.               DW       64                     ;# of directory entries  <RM>
  184. RAMSECT1      DW       256                    ;Total number of sectors     <EM>
  185.               DB       0FEH                   ;Media descriptor
  186. FATSIZE1      DW       FATSIZE                ;# of sectors used by FAT<RM>
  187. BPB_PTR       DW       BPB                    ;BIOS parameter blk ptr array
  188. ;
  189. ;***Current virtual disk information
  190. ;
  191.               DB       'SIZE'      ;                                   <RM>
  192. RAMSIZEK      DW       RAMDISK     ; size in 1k increments             <RM>
  193. RAMSIZEP      DW       RAMDISK*(1024/16)     ; size in paragraphs      <RM>
  194. ;
  195. TOTAL         DW       ?           ;Total sectors to transfer
  196. VERIFY        DB       0           ;Verify 1=YES, 0=NO
  197. START_SEC     DW       0           ;Starting sector number
  198. VDISK_PTR     DW       0           ;Starting sector of virtual disk
  199. USER_DTA      DW       ?,?         ;Pointer to callers DTA                <EM>
  200. BOOT_REC      EQU      $           ;Dummy DOS boot record
  201.               DB       3 DUP(0)    ;3 byte jump to boot code (not bootable)
  202.               DB       'IBM  2.0'
  203.               DW       SECT        ;Number of bytes in a sector        <RM>
  204.               DB       1           ;1 sector per allocation unit
  205.               DW       1           ;1 reserved sector
  206.               DB       2           ;2 FATS
  207.               DW       64          ;Number of directory entries
  208. RAMSECT2      DW       256                  ; total sectors in image  <RM><EM>
  209.               DB       0FEH        ;Single sided 9 sector
  210. FATSIZE2      DW       FATSIZE     ;Number of sectors in FAT           <RM>
  211. ;
  212. ;***Function table
  213. ;
  214. FUNTAB        LABEL    BYTE
  215.               DW       INIT        ;Initialization
  216.               DW       MEDIA_CHECK ;Media check (block only)
  217.               DW       BUILD_BPB   ;Build BPB
  218.               DW       IOCTL_IN    ;IOCTL input
  219.               DW       INPUT       ;Input (read)
  220.               DW       ND_INPUT    ;Non destructive input no wait (ch only)
  221.               DW       IN_STAT     ;Input status
  222.               DW       IN_FLUSH    ;Input flush
  223.               DW       OUTPUT      ;Output (write)
  224.               DW       OUT_VERIFY  ;Output (write) with verify
  225.               DW       OUT_STAT    ;Output status
  226.               DW       OUT_FLUSH   ;Output flush
  227.               DW       IOCTL_OUT   ;IOCTL output
  228. ;
  229. ;***Local procedures
  230. ;
  231. IN_SAVE       PROC     NEAR
  232.               MOV      AX,ES:WORD PTR DTA[BX] ;Save callers DTA
  233.               MOV      CS:USER_DTA,AX
  234.               MOV      AX,ES:WORD PTR DTA+2[BX]
  235.               MOV      CS:USER_DTA+2,AX
  236.               MOV      AX,ES:WORD PTR COUNT[BX]
  237.               XOR      AH,AH
  238.               MOV      CS:TOTAL,AX
  239.               RET
  240. IN_SAVE       ENDP
  241. ;
  242. ;
  243. CALC_ADDR     PROC     NEAR
  244.               MOV      AX,CS:START_SEC       ;Get starting sector number
  245.               MOV      CX,SECT/16            ;Move 512 to CX segment style
  246.               MUL      CX                    ;Multiply to get actual sector
  247.               MOV      DX,CS:VDISK_PTR       ;Get segment of virtual disk
  248.               ADD      DX,AX                 ;Add that seg to initial seg
  249.               MOV      DS,DX                 ;Save that as actual segment
  250.               XOR      SI,SI                 ;It's on a para boundary
  251.               MOV      AX,CS:TOTAL           ;Total # of sectors to read
  252.               MOV      CX,SECT               ;Bytes per sector         <RM>
  253.               MUL      CX                    ;Multiply to get copy length
  254.               OR       AX,AX                 ;Check for greater than 64K
  255.               JNZ      MOVE_IT
  256.               MOV      AX,0FFFFH             ;Move in for 64K
  257. MOVE_IT:      XCHG     CX,AX                 ;Move length to CX
  258.               RET
  259. CALC_ADDR     ENDP
  260.  
  261.  
  262. SECTOR_READ   PROC     NEAR
  263.               CALL     CALC_ADDR             ;Calculate the starting sector
  264.               MOV      ES,CS:USER_DTA+2      ;Set dest (ES:DI) to point
  265.               MOV      DI,CS:USER_DTA        ;**to callers DTA
  266. ;
  267. ;***Check for DTA wrap in case we came through via verify
  268. ;
  269.               MOV      AX,DI       ;Get offset of DTA
  270.               ADD      AX,CX       ;Add copy length to it
  271.               JNC      RC          ;Carry flag=0, no wrap
  272.               MOV      AX,0FFFFH   ;Max length
  273.               SUB      AX,DI       ;Subtract DTA offset from max
  274.               MOV      CX,AX       ;Use that as copy length to avoid wrap
  275. RC:     REP   MOVSB                ;Do the read
  276.               RET
  277. SECTOR_READ   ENDP
  278.  
  279.  
  280. SECTOR_WRITE  PROC     NEAR
  281.               CALL     CALC_ADDR              ;Calculate starting sector
  282.               PUSH     DS
  283.               POP      ES                     ;Establish addressability
  284.               MOV      DI,SI                  ;ES:DI point to disk
  285.               MOV      DS,CS:USER_DTA+2       ;DS:SI point to callers DTA
  286.               MOV      SI,CS:USER_DTA
  287. ;
  288. ;***Check for DTA wrap
  289. ;
  290.               MOV      AX,SI       ;Move DTA offset to AX
  291.               ADD      AX,CX       ;Add copy length to offset
  292.               JNC      WC          ;Carry flag=0, no segment wrap
  293.               MOV      AX,0FFFFH   ;Move in max copy length
  294.               SUB      AX,SI       ;Subtract DTA offset from max
  295.               MOV      CX,AX       ;Use as new copy length to avoid wrap
  296. WC:     REP   MOVSB                ;Do the write
  297.               RET
  298. SECTOR_WRITE  ENDP
  299.               PAGE
  300. ;
  301. ;***Device strategy
  302. ;
  303. DEV_STATEGY:  MOV      CS:RH_SEG,ES ;Save segment of request header ptr
  304.               MOV      CS:RH_OFF,BX ;Save offset of     "      "     "
  305.               RET
  306. ;
  307. ;***Device interrupt handler
  308. ;
  309. DEV_INT:      CLD
  310. ;
  311. ;***Save state of machine
  312. ;
  313.               PUSH     DS
  314.               PUSH     ES
  315.               PUSH     AX
  316.               PUSH     BX
  317.               PUSH     CX
  318.               PUSH     DX
  319.               PUSH     DI
  320.               PUSH     SI
  321. ;
  322. ;***Do branch according to function passed
  323. ;
  324.               MOV      AL,ES:[BX]+2          ;Get function byte
  325.               ROL      AL,1                  ;Get offset into table
  326.               LEA      DI,FUNTAB             ;Get address of function table
  327.               XOR      AH,AH
  328.               ADD      DI,AX
  329.               JMP      WORD PTR[DI]
  330. ;
  331. ;***Initialization
  332. ;
  333. INIT:
  334.               MOV      AX,CS:RAMSIZEK        ; compute size in # sect  <RM>
  335.               CMP      AX,171                ;                         <RM>
  336.               JB       INIT20                ;                         <RM>
  337.               MOV      CS:WORD PTR FATSIZE1,2 ;                        <RM>
  338.               MOV      CS:WORD PTR FATSIZE2,2 ;                        <RM>
  339.               CMP      AX,341                ;                         <RM>
  340.               JB       INIT20                ;                         <RM>
  341.               MOV      CS:WORD PTR FATSIZE1,3 ;                        <RM>
  342.               MOV      CS:WORD PTR FATSIZE2,3 ;                        <RM>
  343. INIT20:                                      ;                         <RM>
  344.               SHL      AX,1                  ;                         <RM>
  345.               MOV      CS:RAMSECT1,AX        ;                         <RM>
  346.               MOV      CS:RAMSECT2,AX        ;                         <RM>
  347.               MOV      CL,5                  ; compute size in paragr  <RM>
  348.               SHL      AX,CL                 ;                         <RM>
  349.               MOV      CS:RAMSIZEP,AX        ;                         <RM>
  350. ;                                                                      <RM>
  351.               PUSH     CS
  352.               POP      DX                    ;Current CS to DX
  353.               LEA      AX,CS:VDISK           ;Get address of virtual disk
  354.               MOV      CL,4
  355.               ROR      AX,CL                 ;Divide by 16 (paragraph form)
  356.               ADD      DX,AX                 ;Add to current CS value
  357.               MOV      CS:VDISK_PTR,0D000H   ;Save as start seg of vdisk   <EM>
  358.            ;  MOV      AX,CS:RAMSIZEP        ;Add size of vdisk in para<RM><EM>
  359.            ;  ADD      DX,AX                  ;**segment of virtual disk   <EM>
  360.               MOV      ES:WORD PTR BR_ADDR_0[BX],0
  361.               MOV      ES:BR_ADDR_1[BX],DX    ;Make that the break address
  362.               MOV      ES:BYTE PTR UNITS[BX],1 ;Number of diskette units
  363.               LEA      DX,BPB_PTR            ;Get addr of BPB ptr array
  364.               MOV      ES:BPB_PTR_OFF[BX],DX  ;Save offset in data packet
  365.               MOV      ES:BPB_PTR_SEG[BX],CS  ;Save segment in data packet
  366.  
  367.               PUSH     DS                     ;Save DS                   <EM-A>
  368.               MOV      AX,40H                 ;BIOS data segment         <EM-A>
  369.               MOV      DS,AX                  ;Set up segment register   <EM-A>
  370.               CMP      WORD PTR DS:[0072H],1234H  ;Check reset mode      <EM-A>
  371.               POP      DS                     ;Restore DS                <EM-A>
  372.               JNZ      COLD_START             ;Initialize Vdisk          <EM-A>
  373.               JMP      HOT_START              ;Skip if boot from keyboard<EM-A>
  374.  
  375.  
  376. COLD_START:          ; Initialize memory to avoid PARITY errors          <EM-A>
  377.               SUB      AX,AX                 ;Byte to write (null)       <EM-A>
  378.               MOV      ES,CS:VDISK_PTR       ;Get start addr of 1st 64K sector
  379.               MOV      CX,8000H              ;Number of bytes to write   <EM-A>
  380.               REP      STOSW                 ;Repeat no. of times in CX  <EM-A>
  381.               MOV      CX,ES                 ;Move to next sector by     <EM-A>
  382.               ADD      CX,1000H              ;adding 1000H to ES         <EM-A>
  383.               MOV      ES,CX                 ;New start addr at E000H    <EM-A>
  384.               MOV      CX,8000H              ;Reset CX counter to 8000H  <EM-A>
  385.               REP      STOSW                 ;Repeat write in second sect<EM-A>
  386.               MOV      ES,CS:VDISK_PTR       ;Restore addr to 1st seg    <EM-A>
  387.  
  388.               XOR      DI,DI                  ;Zero out DI (Boot record)
  389.               LEA      SI,BOOT_REC            ;Address of boot record
  390.               MOV      CX,24
  391.         REP   MOVSB                           ;Copy 24 bytes of boot record
  392.               MOV      CS:WORD PTR START_SEC,1
  393.               MOV      AX,FATSIZE1           ;                         <RM>
  394.               MOV      CS:WORD PTR TOTAL,AX  ;                         <RM>
  395.               CALL     CALC_ADDR              ;Calc addr of logical sect 1
  396.               PUSH     DS
  397.               POP      ES
  398.               MOV      DI,SI                  ;Move that address to ES:DI
  399.               XOR      AL,AL
  400.         REP   STOSB                           ;Zero out FAT area
  401.               MOV      DS:BYTE PTR[SI],0FEH   ;Set the first FAT entry
  402.               MOV      DS:BYTE PTR 1[SI],0FFH
  403.               MOV      DS:BYTE PTR 2[SI],0FFH
  404.               PUSH     DS                     ;Save pointer to FAT on
  405.               PUSH     SI                     ;**the stack
  406.               MOV      AX,CS:WORD PTR START_SEC ;                      <RM>
  407.               ADD      AX,CS:WORD PTR TOTAL     ;                      <RM>
  408.               MOV      CS:WORD PTR START_SEC,AX ;                      <RM>
  409. ;DEL          MOV      CS:WORD PTR TOTAL,2                             <RM>
  410.               CALL     CALC_ADDR              ;Calc addr of logical sect 3
  411.               PUSH     DS
  412.               POP      ES
  413.               MOV      DI,SI                  ;Move that address to ES:DI
  414.               POP      SI
  415.               POP      DS                     ;Restore addr of 1st entry
  416.         REP   MOVSB                           ;Copy first FAT to second FAT
  417.               MOV      AX,CS:WORD PTR START_SEC ;                      <RM>
  418.               ADD      AX,CS:WORD PTR TOTAL     ;                      <RM>
  419.               MOV      CS:WORD PTR START_SEC,AX ;                      <RM>
  420. ;DEL          MOV      CS:WORD PTR START_SEC,5                         <RM>
  421.               MOV      CS:WORD PTR TOTAL,4
  422.               CALL     CALC_ADDR              ;Calc addr of LS 5 (start dir
  423.               XOR      AL,AL
  424.               PUSH     DS
  425.               POP      ES                     ;Set up ES:DI to point to it
  426.               XOR      DI,DI
  427.         REP   STOSB                           ;Zero out directory
  428.               MOV      ES,CS:RH_SEG           ;Restore ES:BX to req header
  429.               MOV      BX,CS:RH_OFF
  430.               STATUS   DONE,NOERROR,0         ;Set status done (noerror)
  431.  
  432.               LEA      DX,COLD_MESSAGE        ;Choose initialize msg    <EM-A>
  433.               JMP      SHORT MESSAGE          ;Go display it            <EM-A>
  434. COLD_MESSAGE  DB       "Hi-RAM disk installed.",13,"$"        ;         <EM-A>
  435. HOT_MESSAGE   DB       "Hi RAM disk preserved.",13,"$"        ;         <EM-A>
  436. HOT_START:    LEA      DX,HOT_MESSAGE         ;Choose preserve msg      <EM-A>
  437. MESSAGE:      PUSH     CS                     ;Current segment          <EM-A>
  438.               POP      DS                     ;Set DS to it             <EM-A>
  439.               MOV      AH,9                   ;DOS print string call    <EM-A>
  440.               INT      21H                    ;Print the string         <EM-A>
  441.  
  442.               JMP      EXIT
  443. ;
  444. ;***Media check
  445. ;
  446. MEDIA_CHECK:  MOV      ES:BYTE PTR RET_BYTE[BX],1
  447.               STATUS   DONE,NOERROR,0         ;turn on the done bit
  448.               JMP      EXIT
  449. ;
  450. ;***Build BIOS parameter block
  451. ;
  452. BUILD_BPB:    PUSH     ES                     ;Save SRH segment
  453.               PUSH     BX                     ;Save SRH offset
  454.               MOV      CS:WORD PTR START_SEC,0
  455.               MOV      CS:WORD PTR TOTAL,1
  456.               CALL     CALC_ADDR             ;Calc addr of 1st sector
  457.               PUSH     CS
  458.               POP      ES
  459.               LEA      DI,BPB                 ;Addr of BIOS parameter block
  460.               ADD      SI,11
  461.               MOV      CX,13                  ;Length of BPB
  462.         REP   MOVSB
  463.               POP      BX                     ;Restore offset of SRH
  464.               POP      ES                     ;Restore segment of SRH
  465.               LEA      DX,BPB                 ;Get BPB array pointer
  466.               MOV      ES:BPBA_PTR[BX],DX     ;Save ptr to BPB table
  467.               MOV      ES:BPBA_PTR+2[BX],CS
  468.               MOV      ES:DTA[BX],DX          ;Offset to sector buffer
  469.               MOV      ES:DTA+2[BX],CS
  470.               STATUS   DONE,NOERROR,0
  471.               JMP      EXIT
  472. ;
  473. ;***The following entries are not supported by this device
  474. ;
  475. IOCTL_IN:
  476. IOCTL_OUT:
  477. ND_INPUT:                          ;Non destructive input no wait (ch only)
  478. IN_STAT:                           ;Input status      "     "
  479. IN_FLUSH:                          ;Input flush
  480. OUT_STAT:                          ;Output status
  481. OUT_FLUSH:                         ;Output flush
  482. ;
  483. ;***Disk read
  484. ;
  485. INPUT:        CALL     IN_SAVE                ;Call the initial save rtn
  486.               MOV      AX,ES:WORD PTR SSN[BX] ;Set starting sector number
  487.               MOV      CS:START_SEC,AX        ;Save starting sector number
  488.               MOV      AX,ES:WORD PTR COUNT[BX]
  489.               MOV      CS:TOTAL,AX            ;Save # sectors to transfer
  490.               CALL     SECTOR_READ            ;Read in that many sectors
  491.               MOV      BX,CS:RH_OFF           ;Restore ES:BX as req header
  492.               MOV      ES,CS:RH_SEG
  493.               STATUS   DONE,NOERROR,0         ;Set status word (done, noerr
  494.               JMP      EXIT
  495. ;
  496. ;***Disk write
  497. ;
  498. OUTPUT:       CALL     IN_SAVE                ;Output (write)
  499.               MOV      AX,ES:WORD PTR SSN[BX] ;Get starting sector number
  500.               MOV      CS:START_SEC,AX        ;Set    "        "      "
  501.               MOV      AX,ES:WORD PTR COUNT[BX]
  502.               MOV      CS:TOTAL,AX            ;Save total sectors to write
  503.               CALL     SECTOR_WRITE
  504.               MOV      BX,CS:RH_OFF           ;Restore ES:BX as req header
  505.               MOV      ES,CS:RH_SEG
  506.               CMP      CS:BYTE PTR VERIFY,0   ;Write verify set
  507.               JZ       NO_VERIFY              ;No, no write verify
  508.               MOV      CS:BYTE PTR VERIFY,0   ;Reset verify indicator
  509.               JMP      INPUT
  510. NO_VERIFY:    STATUS   DONE,NOERROR,0         ;Set status done, no error
  511.               JMP      EXIT
  512. OUT_VERIFY:   MOV      CS:BYTE PTR VERIFY,1   ;Set verify flag
  513.               JMP      OUTPUT                 ;Branch to output routine
  514. ;
  515. ;***Common exit
  516. ;
  517. EXIT:         POP      SI
  518.               POP      DI
  519.               POP      DX
  520.               POP      CX
  521.               POP      BX
  522.               POP      AX
  523.               POP      ES
  524.               POP      DS
  525.               RET
  526. ;
  527. ;
  528. E_O_P:
  529. ;***Macro to align the virtual disk on a paragraph boundary
  530. IF ($-START) MOD 16
  531. ORG           ($-START)+16-(($-START) MOD 16)
  532. ENDIF
  533. VDISK         EQU      $
  534. VDSK          ENDP
  535. CSEG          ENDS
  536.               END      BEGIN
  537.